/**
 * Token的类型
 */
 const TokenType = {
  Plus: 'Plus',   // +
  Minus: 'Minus',  // -
  Star: 'Star',   // *
  Slash: 'Slash',  // /

  GE: 'GE',     // >=
  GT: 'GT',     // >
  EQ: 'EQ',     // ==
  LE: 'LE',     // <=
  LT: 'LT',     // <

  SemiColon: 'SemiColon', // ;
  LeftParen: 'LeftParen', // (
  RightParen: 'RightParen',// )

  Assignment: 'Assignment',// =

  If: 'If',
  Else: 'Else',
  
  Int: 'Int',

  Identifier: 'Identifier',     //标识符

  IntLiteral: 'IntLiteral',     //整型字面量
  StringLiteral: 'StringLiteral'   //字符串字面量
}

/**
 * AST节点的类型。
 */
 const ASTNodeType = {
  Program: 'Program',           //程序入口，根节点

  IntDeclaration: 'IntDeclaration',     //整型变量声明
  ExpressionStmt: 'ExpressionStmt',     //表达式语句，即表达式后面跟个分号
  AssignmentStmt: 'AssignmentStmt',     //赋值语句

  Primary: 'Primary',            //基础表达式
  Multiplicative: 'Multiplicative',     //乘法表达式
  Additive: 'Additive',           //加法表达式

  Identifier: 'Identifier',         //标识符
  IntLiteral: 'IntLiteral'          //整型字面量
}

const SimpleASTNode = require('./SimpleAstNode')

/**
 * 把整型语句，如 int a或int b = 2 * 3转变成声明语句
 * @param {SimpleTokenReader} tokens 
 */
const intDeclare = (tokens) => {
  let node
  let token = tokens.peek() // 预读
  if (token && token.type === TokenType.Int) { // 匹配Int
    token = tokens.read()
    if (tokens.peek().type === TokenType.Identifier) {   //匹配标识符
      token = tokens.read() // 消耗掉标识符
      // 通过阅读首两个单词是int和变量，推断是整型宣告句
      node = new SimpleASTNode(AstNodeType.intDeclare, token.text)
      token = tokens.peek()
      //消耗掉等号
      if (token && token.type === TokenType.Assignment) {
        tokens.read()
        const child = additive(token) // 期待一个加法表达式
        if (!child) {
          throw new Error('The int variable assignment is invalid, expecting an expression')
        } else {
          node.addChild(child)
        }
      }
    } else {
      throw new Error('variable name is expected')
    }

    if (node) {
      token = tokens.peek()
      // 語句結尾應該要有分號
      if (token && token.type === TokenType.SemiColon) {
        tokens.read()
      } else {
        throw new Error('invalid statement, expecting semicolon')
      }
    }
  }

  return node
}